#include <linux/myhead_for_driver.h>

// &i2c1{
// 	pinctrl-names = "default","sleep";
// 	pinctrl-0 = <&i2c1_pins_b>;
// 	pinctrl-1 = <&i2c1_sleep_pins_b>;
// 	clock-frequency = <400000>; //400KHz
// 	i2c-scl-rising-time-ns = <185>;
// 	i2c-scl-falling-time-ns = <20>;
// 	status = "okay";
// 	ap3216c@1E{
// 		compatible = "rhf,ap3216c";
// 		interrupt-parent = <&gpiof>;
// 		interrupts = <13 0>;
// 		reg = <0x1E>;
// 	};
// };

struct device_node *irq_node;
struct work_struct work;
int irq_num;

struct i2c_client *client_global;

#define CNAME "ap3216c_driver"
int major;
struct class *cls;
struct device *dev;

int write_pos(u8 reg, u8 cmd)
{
    u8 send_buf[2] = {reg, cmd};
    u16 res;
    struct i2c_msg msgs[] = {
        {.addr = client_global->addr,
         .flags = 0,
         .len = 2,
         .buf = send_buf},
    };
    res = i2c_transfer(client_global->adapter, msgs, 1);
    if (ARRAY_SIZE(msgs) != res)
    {
        printk("read_pos error,pls try again!\n");
        return -EAGAIN;
    }
    return 0;
}

int read_pos(u8 reg)
{
    u8 reg_buf = reg;
    u8 data_buf;
    u16 res;
    struct i2c_msg msgs[] = {
        {.addr = client_global->addr,
         .flags = 0,
         .len = 1,
         .buf = &reg_buf},
        {.addr = client_global->addr,
         .flags = 1,
         .len = 1,
         .buf = &data_buf}};
    res = i2c_transfer(client_global->adapter, msgs, 2); // 这里的2是消息的个数
    if (ARRAY_SIZE(msgs) != res)
    {
        printk("read_pos error,pls try again!\n");
        return -EAGAIN;
    }
    return 0;

    return data_buf;
}

u8 read_light(u8 reg)
{
    u8 reg_buf = reg;
    u8 data_buf;
    u8 res;
    struct i2c_msg msgs[] = {
        {.addr = client_global->addr,
         .flags = 0,
         .len = 1,
         .buf = &reg_buf},
        {.addr = client_global->addr,
         .flags = 1,
         .len = 1,
         .buf = &data_buf}};
    res = (u8)i2c_transfer(client_global->adapter, msgs, 2);
    // ioread8
    if (ARRAY_SIZE(msgs) != res)
    {
        printk("read_light error,pls try again!\n");
        return -EAGAIN;
    }
    return data_buf;
}

irqreturn_t do_int_irq(int irq_id, void *val)
{

    schedule_work(&work);
    return IRQ_HANDLED;
}
void do_int_irq_bottom(struct work_struct *work)
{
    // printk("测试\n"); // is ok
    // 使用阻塞的方式给用户也可以
    // write_pos(0x02, 0x1);
    // write_pos(0x01, 0x3);

    // 暂时不做处理 因为只需要读取光照强度
}

struct of_device_id oftable[] = {
    {.compatible = "rhf2,ap3216c"},
    {},
};

int ap3216c_open(struct inode *inode, struct file *filp)
{
    return 0;
}

int ap3216c_close(struct inode *inode, struct file *filp)
{
    return 0;
}

ssize_t ap3216c_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    u16 data;
    u8 data_h;
    u8 data_l;
    // write_pos(0x10,0x3); // 设置读取range4 公式为res * 0.0049 不设置默认是range1
    data_l = read_light(0x0C);
    // printk("ldata = %d\n", data_l); //demo
    data_h = read_light(0x0B);
    // printk("hdata = %d\n", data_h); //demo
    data = (data_h << 8) | data_l;
    // printk("data = %d\n", data); //demo
    //发送给用户
    copy_to_user(buf, &data, 2);
    return 0;
}

ssize_t ap3216c_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{

    return 1;
}

static const struct file_operations ap3216c_fops = {
    .open = ap3216c_open,
    .release = ap3216c_close,
    .read = ap3216c_read,
    .write = ap3216c_write,
};

int ap3216c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    int err, res;
    client_global = client;
    // irq_node = of_find_node_by_path("/xxx");
    // if (NULL == irq_node)
    // {
    //     err = -EPERM;
    // }
    // irq_num = irq_of_parse_and_map(irq_node, 0);
    irq_num = client->irq;
    // write//软件复位
    write_pos(0x0, 0x4);
    mdelay(10);
    write_pos(0x0, 0x3);
    if ((res = request_irq(irq_num, do_int_irq, IRQF_TRIGGER_FALLING, "int_irq", NULL)))
    {
        err = res;
        goto ERR0;
    }
    INIT_WORK(&work, do_int_irq_bottom);

    major = register_chrdev(0, CNAME, &ap3216c_fops);
    if (major < 0)
    {
        err = major;
        goto ERR1;
    }
    cls = class_create(THIS_MODULE, CNAME);
    if (IS_ERR(cls))
    {
        err = PTR_ERR(cls);
        goto ERR2;
    }
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, CNAME);
    if (IS_ERR(dev))
    {
        err = PTR_ERR(dev);
        goto ERR3;
    }

    return 0;
ERR3:
    class_destroy(cls);
ERR2:
    unregister_chrdev(major, CNAME);
ERR1:
    free_irq(irq_num, NULL);
ERR0:
    return err;
}
int ap3216c_remove(struct i2c_client *client)
{
    write_pos(0, 0);
    device_destroy(cls, MKDEV(major, 0));
    unregister_chrdev(major, CNAME);
    class_destroy(cls);
    free_irq(irq_num, NULL);
    return 0;
}
struct i2c_driver ap3216c_drv = {
    .probe = ap3216c_probe,
    .remove = ap3216c_remove,
    .driver = {
        .name = "rhf2",
        .of_match_table = oftable,
    },
};
module_i2c_driver(ap3216c_drv);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("rhf xxx@xxx.com");